///
/// Author: Nguyen Duc Duy
/// Email: ducduy181086@gmail.com
///
using System;
using System.DHTML;
using Sys;

using JQuerySharp;

namespace DataBindingScript
{
    public delegate void SimpleDelegate();
    public delegate void GenericOneArgDelegate(object arg1);
    public delegate void GenericTwoArgDelegate(object arg1, object arg2);
    public delegate void GenericThreeArgDelegate(object arg1, object arg2, object arg3);

    public class JsonResult
    {
        [IntrinsicProperty]
        public object this[string key] { get { return null; } set { } }
    }

    public class DataRepeater
    {
        DOMElement _parent = null;
        DOMElement _itemRep = null;
        DOMElement _itemRep2 = null;
        int _position = -1;
        int _itemCount = 0;

        public int Count()
        {
            return ((jQuery)(object)_parent).QuerySelectorAll("[id*=_child_]").Length;
        }

        public DataRepeater(string selector, string altSelector)
        {
            //string selector = (elementId != "" ? "#" : "") + elementId;
            //string altSelector = (altElementId != "" ? "#" : "") + altElementId;
            jQuery jTable = JQueryFactory.JQuery(selector);
            jQuery altJTable = JQueryFactory.JQuery(altSelector);
            if (jTable.Length > 0)
            {
                _parent = jTable[0].ParentNode;
                _itemRep = jTable[0];
                _itemRep.ID = "jQ" + Math.Random().ToString().Substring(2, 10);
                if (altSelector != null && altSelector != "")
                {
                    _itemRep2 = altJTable[0];
                    _itemRep2.ID = "jQ" + Math.Random().ToString().Substring(2, 10);
                }
                int count = _parent.ChildNodes.Length;
                for (int i = 0; i < count; i++)
                {
                    if (_parent.ChildNodes[i] == _itemRep)
                    {
                        _position = i;
                        break;
                    }
                }
                _parent.RemoveChild(_itemRep);
                if (_itemRep2 != null) _parent.RemoveChild(_itemRep2);
            }
        }

        public void DeleteItem(DOMElement item)
        {
            _parent.RemoveChild(item);
        }

        public void BindData(JsonResult[] dataJson, object flags, GenericOneArgDelegate onBinding) // flags: (null overwrite) (-1 append) (0... position)
        {
            if (_position < 0) return;
            int dataCount = dataJson.Length;
            for (int i = _itemCount - 1; flags == null && i >= 0; i--)
            {
                DOMElement child = _parent.ChildNodes[i + _position];
                _parent.RemoveChild(child);
            }
            int adv = 0;
            int preItemCount = _itemCount;
            if ((int)flags == -1) adv = _itemCount;
            else if ((int)flags > -1) adv = (int)flags;
            _itemCount = (flags == null ? 0 : _itemCount) + dataCount;
            if (_position + adv < _parent.ChildNodes.Length)
            {
                DOMElement itemRef = _parent.ChildNodes[(int)flags == -1 ? _position + adv : adv];
                DataBinding obj = new DataBinding();
                bool isAlt = false;
                for (int i = 0; i < dataCount; i++)
                {
                    DOMElement item = isAlt && _itemRep2 != null ? _itemRep2.CloneNode(true) : _itemRep.CloneNode(true);
                    item.ID = string.Format("{0}_child_{1}", item.ID, i + adv + (flags == null || (int)flags == -1 ? 0 : preItemCount));
                    _parent.InsertBefore(item, itemRef);
                    //if (flags != null && (int)flags != -1) itemRef = item;
                    obj.BindData(dataJson[i], item.ID);

                    isAlt = !isAlt;
                    Script.Literal("{0}.$dataJson = {1}", item, dataJson[i]);
                    if (onBinding != null) onBinding(item);
                }
            }
            else if (_position + adv == _parent.ChildNodes.Length)
            {
                DataBinding obj = new DataBinding();
                bool isAlt = false;
                for (int i = 0; i < dataCount; i++)
                {
                    DOMElement item = isAlt && _itemRep2 != null ? _itemRep2.CloneNode(true) : _itemRep.CloneNode(true);
                    item.ID = string.Format("{0}_child_{1}", item.ID, i + adv + (flags == null || (int)flags == -1 ? 0 : preItemCount));
                    _parent.AppendChild(item);
                    obj.BindData(dataJson[i], item.ID);

                    isAlt = !isAlt;
                    Script.Literal("{0}.$dataJson = {1}", item, dataJson[i]);
                    if (onBinding != null) onBinding(item);
                }
            }
        }

        [AlternateSignature]
        public extern void BindDataHref(string href);
        [AlternateSignature]
        public extern void BindDataHref(string href, GenericOneArgDelegate onSuccess);

        public void BindDataHref(string href, GenericOneArgDelegate onSuccess, SimpleDelegate onDeny)
        {
            jQuery.AjaxSetup(new Dictionary("cache", false));
            JQueryFactory.JQuery("").AjaxError((Function)(object)new GenericThreeArgDelegate(delegate(object data1, object data2, object data3)
            {
                Script.Alert("error");
            }));
            jQuery.GetJSON(href, new Dictionary(), (Function)(object)new GenericOneArgDelegate(delegate(object data)
            {
                if ((int)data == DataBinding.AuthenFail && onDeny != null) onDeny();
                BindData((JsonResult[])data, null, null);
                if (onSuccess != null)
                {
                    onSuccess(data);
                }
            }));
        }
    }

    public class DataGrid
    {
        string[] _vals = null;
        DOMElement[] _cols = null;
        DOMElement _row = null;
        string _rowAltClass = "";
        DOMElement _table = null;
        DOMElement _tableTmp = null;

        private void SetTextContent(DOMElement element, string text)
        {
            if (DataBinding.IsFireFox())
            {
                while (element.FirstChild != null) element.RemoveChild(element.FirstChild);
                element.AppendChild(Document.CreateTextNode(text));
            }
            else
            {
                element.InnerText = text;
            }
        }

        private string GetPath(DOMElement parent, DOMElement element)
        {
            if (parent == element) return "";

            string result = "";
            int count = parent.ChildNodes.Length;
            for (int i = 0; i < count; i++)
            {
                if (parent.ChildNodes[i] == element)
                {
                    result += i.ToString();
                    break;
                }
                else
                {
                    string tmpStr = GetPath(parent.ChildNodes[i], element);
                    if (tmpStr.Length > 0)
                    {
                        result += i.ToString() + "," + tmpStr;
                        break;
                    }
                }
            }
            return result;
        }

        public DataGrid(string elementId)
        {
            string selector = (elementId != "" ? "#" : "") + elementId;
            jQuery jTable = JQueryFactory.JQuery(selector);
            if (jTable.Length > 0 && jTable[0].TagName.ToLowerCase() == "table")
            {
                string selector1 = string.Format("{0} tr td[BindName]", selector);
                jQuery fields = JQueryFactory.JQuery(selector1);
                int count = fields.Length;
                if (count > 0)
                {
                    _vals = new string[count];
                    _cols = new DOMElement[count];
                    _row = fields[0].ParentNode;
                    _rowAltClass = (string)_row.GetAttribute("RowAlt");
                    if (_rowAltClass != null && _rowAltClass != "") _row.RemoveAttribute("RowAlt");
                    _table = _row.ParentNode;
                }
                for (int i = 0; i < count; i++)
                {
                    string name = (string)fields[i].GetAttribute("BindName");
                    string selector2 = string.Format("{0} tr td[BindName=\"{1}\"][BindValue], {0} tr td[BindName=\"{1}\"] [BindValue]", selector, name);
                    jQuery fieldValues = JQueryFactory.JQuery(selector2);
                    int countValues = fieldValues.Length;
                    string vals = "";
                    for (int j = 0; j < countValues; j++)
                    {
                        vals += (fields[i] == fieldValues[j] ? "m" : GetPath(fields[i], fieldValues[j])) + ";";
                    }
                    _vals[i] = vals.Length > 0 ? vals.Substr(0, vals.Length - 1) : vals;
                    _cols[i] = DataBinding.DetachElement(fields[i]);
                }
                if (_row != null) _row.ParentNode.RemoveChild(_row);
            }
        }

        public void BindData(JsonResult[] dataJson)
        {
            if (_cols == null) return;
            if (_cols.Length == 0) return;

            int dataCount = dataJson.Length;
            int count = _cols.Length;

            if (_tableTmp == null) _tableTmp = _table.CloneNode(true);
            DOMElement table = _tableTmp.CloneNode(true);
            _table.ParentNode.ReplaceChild(table, _table);
            _table = table;
            for (int i = 0; i < dataCount; i++)
            {
                DOMElement tr = _row.CloneNode(true);
                if (i % 2 == 1 && _rowAltClass != null && _rowAltClass != "") tr.SetAttribute("class", _rowAltClass);
                _table.AppendChild(tr);
                for (int j = 0; j < count; j++)
                {
                    DOMElement field = _cols[j].CloneNode(true);
                    tr.AppendChild(field);
                    string name = (string)field.GetAttribute("BindName");
                    field.RemoveAttribute("BindName");

                    string[] vals = _vals[j].Split(";");
                    int countVal = vals.Length;
                    for (int k = 0; k < countVal; k++)
                    {
                        if (vals[k] == "m")
                        {
                            field.RemoveAttribute("BindValue");
                            //field.InnerText = (string)dataJson[i][name];
                            SetTextContent(field, (string)dataJson[i][name]);
                        }
                        else
                        {
                            string[] childIndexs = vals[k].Split(",");
                            int childIndexsCount = childIndexs.Length;
                            DOMElement elementCur = field;
                            for (int l = 0; l < childIndexsCount; l++)
                            {
                                elementCur = elementCur.ChildNodes[(int)(object)childIndexs[l]];
                            }
                            string valueType = (string)elementCur.GetAttribute("BindValue");
                            elementCur.RemoveAttribute("BindValue");
                            if (valueType == "inner")
                            {
                                SetTextContent(elementCur, (string)dataJson[i][name]);
                            }
                            else
                            {
                                elementCur.SetAttribute(valueType, dataJson[i][name]);
                            }
                        }
                    }
                }
            }
        }

        [AlternateSignature]
        public extern void BindDataHref(string href);
        [AlternateSignature]
        public extern void BindDataHref(string href, GenericOneArgDelegate onSuccess);

        public void BindDataHref(string href, GenericOneArgDelegate onSuccess, SimpleDelegate onDeny)
        {
            jQuery.AjaxSetup(new Dictionary("cache", false));
            JQueryFactory.JQuery("").AjaxError((Function)(object)new GenericThreeArgDelegate(delegate(object data1, object data2, object data3)
            {
                Script.Alert("error");
            }));
            jQuery.GetJSON(href, new Dictionary(), (Function)(object)new GenericOneArgDelegate(delegate(object data)
            {
                if ((int)data == DataBinding.AuthenFail && onDeny != null) onDeny();
                BindData((JsonResult[])data);
                if (onSuccess != null)
                {
                    onSuccess(data);
                }
            }));
        }
    }

    public class DataBinding
    {
        static public int AuthenFail = 0;

        static public bool IsFireFox()
        {
            return (string)Script.Literal("window.navigator.appName") == "Netscape";
        }

        static public bool Equal(Dictionary data1, Dictionary data2)
        {
            bool result = true;
            foreach (DictionaryEntry item in data1)
            {
                if (item.Value != data2[item.Key])
                {
                    result = false;
                    break;
                }
            }
            return result;
        }

        static public bool ClearDataForm(string parentId)
        {
            string selector = parentId != "" ? "#{0} input[BindName], #{0} select[BindName], #{0} textarea[BindName]" : "input[BindName], select[BindName], textarea[BindName]";
            selector = string.Format(selector, parentId);
            jQuery fields = JQueryFactory.JQuery(selector);

            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string fieldName = (string)field.GetAttribute("BindName");
                if (field.TagName.ToLowerCase() == "input")
                {
                    string fieldType = (string)field.GetAttribute("type");
                    switch (fieldType)
                    {
                        case "text":
                        case "hidden":
                        case "password":
                            ((TextElement)field).Value = "";
                            break;
                        case "checkbox":
                            ((CheckBoxElement)field).Checked = false;
                            break;
                        case "image":
                            field.SetAttribute("src", "");
                            break;
                        case "radio":
                            //dataForm[fieldName] = GetValueRadio(field, parentId);
                            break;
                        default:
                            break;
                    }
                }
                else if (field.TagName.ToLowerCase() == "select")
                {
                    ((SelectElement)field).Value = "";
                }
                else if (field.TagName.ToLowerCase() == "textarea")
                {
                    ((TextAreaElement)field).Value = "";
                }
            }
            return true;
        }

        static private bool ContainString(Array source, string str)
        {
            int count = source.Length;
            for (int i = 0; i < count; i++)
            {
                if (source[i] == str) return true;
            }
            return false;
        }

        static public Dictionary SerializeDataEachElement(DOMElement selectorMask)
        {
            string selectorElement = "input[BindName], select[BindName], textarea[BindName]";
            jQuery fields = ((jQuery)(object)selectorMask).QuerySelectorAll(selectorElement);

            Dictionary dataForm = new Dictionary();
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string fieldName = (string)field.GetAttribute("BindName");
                if (field.TagName.ToLowerCase() == "input")
                {
                    string fieldType = (string)field.GetAttribute("type");
                    switch (fieldType)
                    {
                        case null:
                        case "":
                        case "text":
                        case "hidden":
                        case "password":
                            //dataForm[fieldName] = field.GetAttribute("value");
                            dataForm[fieldName] = ((TextElement)field).Value;
                            break;
                        case "checkbox":
                            dataForm[fieldName] = ((CheckBoxElement)field).Checked;
                            break;
                        case "image":
                            dataForm[fieldName] = field.GetAttribute("src");
                            break;
                        case "radio":
                            dataForm[fieldName] = GetValueRadioSelector(field, selectorMask);
                            break;
                        default:
                            break;
                    }
                }
                else if (field.TagName.ToLowerCase() == "select")
                {
                    dataForm[fieldName] = ((SelectElement)field).Value;
                }
                else if (field.TagName.ToLowerCase() == "textarea")
                {
                    //dataForm[fieldName] = field.InnerHTML;
                    dataForm[fieldName] = ((TextAreaElement)field).Value;
                }
            }
            return dataForm;
        }

        static public Array SerializeDataArray(string selector)
        {
            jQuery rows = JQueryFactory.JQuery(selector);
            int count = rows.Length;
            Array result = new Array();
            for (int i = 0; i < count; i++)
            {
                result = result.Concat(SerializeDataEachElement(rows[i]));
            }

            return result;
        }

        static public Dictionary SerializeData(string parentId)
        {
            string selector = parentId != "" ? "#{0} input[BindName], #{0} select[BindName], #{0} textarea[BindName]" : "input[BindName], select[BindName], textarea[BindName]";
            selector = string.Format(selector, parentId);
            jQuery fields = JQueryFactory.JQuery(selector);

            Dictionary dataForm = new Dictionary();
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string fieldName = (string)field.GetAttribute("BindName");
                if (field.TagName.ToLowerCase() == "input")
                {
                    string fieldType = (string)field.GetAttribute("type");
                    switch (fieldType)
                    {
                        case null:
                        case "":
                        case "text":
                        case "hidden":
                        case "password":
                            //dataForm[fieldName] = field.GetAttribute("value");
                            dataForm[fieldName] = ((TextElement)field).Value;
                            break;
                        case "checkbox":
                            dataForm[fieldName] = ((CheckBoxElement)field).Checked;
                            break;
                        case "image":
                            dataForm[fieldName] = field.GetAttribute("src");
                            break;
                        case "radio":
                            dataForm[fieldName] = GetValueRadio(field, parentId);
                            break;
                        default:
                            break;
                    }
                }
                else if (field.TagName.ToLowerCase() == "select")
                {
                    dataForm[fieldName] = ((SelectElement)field).Value;
                }
                else if (field.TagName.ToLowerCase() == "textarea")
                {
                    //dataForm[fieldName] = field.InnerHTML;
                    dataForm[fieldName] = ((TextAreaElement)field).Value;
                }
            }
            return dataForm;
        }

        static public string SerializeData2(string parentId)
        {
            //Dictionary data = SerializeData(parentId);
            //return (string)Script.Literal("JSON.stringify(data)");
            string result = "{";
            Dictionary tmp = SerializeData(parentId);
            foreach (DictionaryEntry item in tmp)
            {
                
                result += (string.Format("'{0}':'{1}'", item.Key, item.Value) + ",");
            }
            result = result.Substr(0, result.Length - 1) + "}";
            return result;
        }

        static public DOMElement DetachElement(DOMElement element)
        {
            if (element == null) return null;
            element.ParentNode.RemoveChild(element);
            return element;
        }

        static public DOMElement DetachElementId(string parentId)
        {
            if (parentId == "") return null;
            jQuery jElement = JQueryFactory.JQuery(string.Format("#{0}", parentId));
            if (jElement.Length == 0) return null;
            DOMElement result = jElement[0];
            result.ParentNode.RemoveChild(result);

            return result;
        }

        [AlternateSignature]
        public extern void PostData(string href, string parentId);
        [AlternateSignature]
        public extern void PostData(string href, string parentId, GenericOneArgDelegate onSuccess);

        public void PostData(string href, string parentId, GenericOneArgDelegate onSuccess, SimpleDelegate onDeny)
        {
            Dictionary dataForm = SerializeData(parentId);

            jQuery.AjaxSetup(new Dictionary("cache", false));
            //jQuery.Ajax(new Dictionary("type", "post", "url", href, "data", dataForm, "contentType", "application/json;charset=utf-8", "dataType", "json", "async", false, "success", onSuccess, "error", onDeny));
            jQuery.Post(href, dataForm, (Function)(object)new GenericOneArgDelegate(delegate(object data)
            {
                if ((int)data == AuthenFail && onDeny != null) onDeny();
                Script.Eval("data = " + data);
                if (onSuccess != null)
                {
                    onSuccess(data);
                }
            }));
        }

        public void PostDataAjax(string href, string parentId, GenericOneArgDelegate onSuccess, GenericOneArgDelegate onFailed)
        {
            string dataForm = SerializeData2(parentId);
            PostDataAjaxStringJson(href, dataForm, onSuccess, onFailed);
        }

        public void PostDataAjaxStringJson(string href, string jsonStr, GenericOneArgDelegate onSuccess, GenericOneArgDelegate onFailed)
        {
            jQuery.AjaxSetup(new Dictionary("cache", false));
            jQuery.Ajax(new Dictionary("type", "post", "url", href, "data", jsonStr, "contentType", "application/json;charset=utf-8", "dataType", "json", "async", false, "success", onSuccess, "error", onFailed));
        }

        [AlternateSignature]
        public extern void GetData(string href, string parentId);
        [AlternateSignature]
        public extern void GetData(string href, string parentId, GenericOneArgDelegate onSuccess);

        public void GetData(string href, string parentId, GenericOneArgDelegate onSuccess, SimpleDelegate onDeny)
        {
            jQuery.AjaxSetup(new Dictionary("cache", false));
            JQueryFactory.JQuery("").AjaxError((Function)(object)new GenericThreeArgDelegate(delegate(object data1, object data2, object data3)
            {
                Script.Alert("error");
            }));
            jQuery.GetJSON(href, new Dictionary(), (Function)(object)new GenericOneArgDelegate(delegate(object data)
            {
                if ((int)data == AuthenFail && onDeny != null) onDeny();
                BindData((JsonResult)data, parentId);
                if (onSuccess != null)
                {
                    onSuccess(data);
                }
            }));
        }

        public void BindData(JsonResult dataJson, string parentId)
        {
            RegisterOnSuccessBindData();

            BindTextArea(dataJson, parentId);
            BindComboBox(dataJson, parentId);
            BindInput(dataJson, parentId);
            BindLabel(dataJson, parentId);
            BindInnerHtml(dataJson, parentId);

            RaiseOnSuccessBindData();
        }

        private static void SetModelStatus(JsonResult dataJson, DOMElement field, string name)
        {
            if (dataJson["ModelStatus"] != null)
            {
                Dictionary fieldAtt = (Dictionary)((JsonResult)dataJson["ModelStatus"])[name];
                if (fieldAtt != null)
                {
                    foreach (DictionaryEntry att in fieldAtt)
                    {
                        field.SetAttribute(att.Key, att.Value);
                    }
                }
            }
        }

        private void BindTextArea(JsonResult dataJson, string parentId)
        {
            string selector = (parentId != "" ? "#" : "") + parentId;
            selector += " textarea[BindName]";
            jQuery fields = JQueryFactory.JQuery(selector);
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string name = (string)field.GetAttribute("BindName");
                string format = (string)field.GetAttribute("DateFormat");
                //field.InnerHTML = (string)dataJson[name];
                if (dataJson[name] != null)
                    ((TextAreaElement)field).Value = (format == null || format == "") ? (string)dataJson[name] : new DateTime(int.ParseInvariant(((string)dataJson[name]).Substring(6, ((string)dataJson[name]).Length - 2))).Format(format);

                SetModelStatus(dataJson, field, name);
            }
        }

        private void BindComboBox(JsonResult dataJson, string parentId)
        {
            string selector = (parentId != "" ? "#" : "") + parentId;
            selector += " select[BindName]";
            jQuery fields = JQueryFactory.JQuery(selector);
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string name = (string)field.GetAttribute("BindName");
                string src = (string)field.GetAttribute("BindSrc");

                if (src != null && src != "")
                {
                    RegisterOnSuccessBindData();
                    jQuery.GetJSON(src, new Dictionary(), (Function)(object)new GenericOneArgDelegate(delegate(object data)
                    {
                        Array dataCombo = (Array)data;
                        string comboValue = (string)field.GetAttribute("BindValue");
                        string comboDesc = (string)field.GetAttribute("BindText");

                        int lengthItems = dataCombo.Length;
                        if (lengthItems > 0)
                        {
                            field.InnerHTML = "";
                        }
                        for (int j = 0; j < lengthItems; j++)
                        {
                            JsonResult dataItem = (JsonResult)dataCombo[j];
                            DOMElement elOption = Document.CreateElement("option");
                            elOption.SetAttribute("value", dataItem[comboValue]);
                            if (dataItem[comboValue] == dataJson[name])
                            {
                                ((CheckBoxElement)elOption).Checked = true;
                                //elOption.SetAttribute("selected", "selected");
                            }
                            elOption.InnerHTML = (string)dataItem[comboDesc];
                            field.AppendChild(elOption);
                        }
                        RaiseOnSuccessBindData();
                    }));
                }
                else
                {
                    jQuery optElements = JQueryFactory.JQuery(selector + " option");
                    int lengthItem = optElements.Length;
                    for (int j = 0; j < lengthItem; j++)
                    {
                        CheckBoxElement elOption = (CheckBoxElement)optElements[j];
                        if (elOption.Value == dataJson[name])
                        {
                            ((CheckBoxElement)elOption).Checked = true;
                        }
                    }
                }
                SetModelStatus(dataJson, field, name);
            }
        }

        private void BindInput(JsonResult dataJson, string parentId)
        {
            string selector = (parentId != "" ? "#" : "") + parentId;
            selector += " input[BindName]";
            jQuery fields = JQueryFactory.JQuery(selector);
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string name = (string)field.GetAttribute("BindName");
                string format = (string)field.GetAttribute("DateFormat");
                bool check = false;

                string type = (string)field.GetAttribute("type");
                if (type == null)
                {
                    type = "text";
                }
                switch (type.ToLowerCase())
                {
                    case "":
                    case "text":
                    case "hidden":
                    case "password":
                        //field.SetAttribute("value", dataJson[name]);
                        if (dataJson[name] != null)
                            ((InputElement)field).Value = (format == null || format == "") ? (string)dataJson[name] : new DateTime(int.ParseInvariant(((string)dataJson[name]).Substring(6, ((string)dataJson[name]).Length - 2))).Format(format);
                        break;
                    case "checkbox":
                        check = (bool)dataJson[name];
                        ((CheckBoxElement)field).Checked = check;
                        //if (check)
                        //{
                        //    field.SetAttribute("checked", "checked");
                        //}
                        //else
                        //{
                        //    field.RemoveAttribute("checked");
                        //}
                        break;
                    case "image":
                        //field.SetAttribute("src", dataJson[name]);
                        ((ImageElement)field).Src = (string)dataJson[name];
                        break;
                    case "radio":
                        BindRadio(dataJson, field);
                        break;
                    default:
                        break;
                }

                SetModelStatus(dataJson, field, name);
            }
        }

        private void BindRadio(JsonResult dataJson, DOMElement field)
        {
            string radioNameAtt = (string)field.GetAttribute("BindName");
            string nameRadio = (string)field.GetAttribute("popupId");
            string src = (string)field.GetAttribute("BindSrc");

            if (field.ID != "")
            {
                jQuery labelField = JQueryFactory.JQuery(string.Format("label[for=\"{0}\"", field.ID));
                field.ParentNode.RemoveChild(labelField[0]);
                jQuery radioChild = JQueryFactory.JQuery(string.Format("input[ChildOf=\"{0}\"]", field.ID));
                for (int i = 0; i < radioChild.Length; i++)
                {
                    string idItem = radioChild[0].ID;
                    jQuery lablesDel = JQueryFactory.JQuery(string.Format("label[for=\"{0}\"", idItem));
                    field.ParentNode.RemoveChild(lablesDel[0]);
                    field.ParentNode.RemoveChild(radioChild[0]);
                }
            }
            if (((InputElement)field).Name == null || ((InputElement)field).Name == "")
            {
                ((InputElement)field).Name = "jQName" + Math.Random().ToString().Substring(2, 10);
            }

            if (src != null && src != "")
            {
                RegisterOnSuccessBindData();
                jQuery.GetJSON(src, new Dictionary(), (Function)(object)new GenericOneArgDelegate(delegate(object data)
                {
                    Array dataRadio = (Array)data;
                    string radioValue = (string)field.GetAttribute("BindValue");
                    string radioDesc = (string)field.GetAttribute("BindText");
                    int lengthItems = dataRadio.Length;
                    DOMElement parentField = field.ParentNode;

                    for (int i = 0; i < lengthItems - 1; i++)
                    {
                        JsonResult dataItem = (JsonResult)dataRadio[i];
                        DOMElement radioInput = Document.CreateElement("input");
                        radioInput.SetAttribute("type", "radio");
                        radioInput.SetAttribute("popupId", nameRadio);
                        radioInput.SetAttribute("id", nameRadio + i.ToString());
                        radioInput.SetAttribute("ChildOf", nameRadio + (lengthItems - 1).ToString());
                        radioInput.SetAttribute("name", ((InputElement)field).Name);
                        if (dataItem[radioValue] == dataJson[radioNameAtt])
                        {
                            ((CheckBoxElement)radioInput).Checked = true;
                        }
                        //radioInput.SetAttribute("value", dataItem[radioValue]);
                        ((CheckBoxElement)radioInput).Value = (string)dataItem[radioValue];
                        DOMElement labelField = Document.CreateElement("label");
                        labelField.SetAttribute("for", nameRadio + i.ToString());
                        labelField.InnerHTML = (string)dataItem[radioDesc];

                        parentField.InsertBefore(radioInput, field);
                        parentField.InsertBefore(labelField, field);
                    }
                    if (lengthItems > 0)
                    {
                        JsonResult dataItem = (JsonResult)dataRadio[lengthItems - 1];
                        field.SetAttribute("id", nameRadio + (lengthItems - 1).ToString());
                        if (dataItem[radioValue] == dataJson[radioValue])
                        {
                            ((CheckBoxElement)field).Checked = true;
                        }
                        //field.SetAttribute("value", dataItem[radioValue]);
                        ((CheckBoxElement)field).Value = (string)dataItem[radioValue];
                        DOMElement labelField = Document.CreateElement("label");
                        labelField.SetAttribute("for", nameRadio + (lengthItems - 1).ToString());
                        labelField.InnerText = (string)dataItem[radioDesc];

                        if (parentField.LastChild == field)
                        {
                            parentField.AppendChild(labelField);
                        }
                        else
                        {
                            DOMElement nextOfField = field.NextSibling;
                            parentField.InsertBefore(labelField, nextOfField);
                        }
                    }
                    RaiseOnSuccessBindData();
                }));
            }
            else
            {
                jQuery radiosJQuery = JQueryFactory.JQuery(string.Format("[name={0}]", ((CheckBoxElement)field).Name));
                int count = radiosJQuery.Length;
                for (int i = 0; i < count; i++)
                {
                    CheckBoxElement item = (CheckBoxElement)radiosJQuery[i];
                    if (item.Value == (string)dataJson[radioNameAtt])
                    {
                        item.Checked = true;
                    }
                }
            }
        }

        private void BindLabel(JsonResult dataJson, string parentId)
        {
            string selector = (parentId != "" ? "#" : "") + parentId;
            selector += " label[BindName]";
            jQuery fields = JQueryFactory.JQuery(selector);
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string name = (string)field.GetAttribute("BindName");
                string format = (string)field.GetAttribute("DateFormat");
                if (dataJson[name] != null)
                    field.InnerHTML = (format == null || format == "") ? (string)dataJson[name] : new DateTime(int.ParseInvariant(((string)dataJson[name]).Substring(6, ((string)dataJson[name]).Length - 2))).Format(format);
                //((TextElement)field).Value = (format == null || format == "") ? (string)dataJson[name] : new DateTime((string)dataJson[name]).Format(format);
                SetModelStatus(dataJson, field, name);
            }
        }

        private void BindInnerHtml(JsonResult dataJson, string parentId)
        {
            string selector = (parentId != "" ? "#" : "") + parentId;
            selector += " :not(input,select,label,textarea)[BindName]";
            jQuery fields = JQueryFactory.JQuery(selector);
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                DOMElement field = fields[i];
                string name = (string)field.GetAttribute("BindName");
                string format = (string)field.GetAttribute("DateFormat");
                string strAtt = (string)field.GetAttribute("BindAttribute");
                if (dataJson[name] != null)
                {
                    if (strAtt == null || strAtt == "")
                        field.InnerHTML = (format == null || format == "") ? (string)dataJson[name] : new DateTime(int.ParseInvariant(((string)dataJson[name]).Substring(6, ((string)dataJson[name]).Length - 2))).Format(format);
                    else
                    {
                        field.SetAttribute(strAtt, (format == null || format == "") ? (string)dataJson[name] : new DateTime(int.ParseInvariant(((string)dataJson[name]).Substring(6, ((string)dataJson[name]).Length - 2))).Format(format));
                    }
                }
                //((TextElement)field).Value = (format == null || format == "") ? (string)dataJson[name] : new DateTime((string)dataJson[name]).Format(format);
                SetModelStatus(dataJson, field, name);
            }
        }

        private void GetOnceDataJson(string href, Dictionary cached, GenericOneArgDelegate onSuccess)
        {
            object dataJson = cached[href];
            if (dataJson == null)
            {
                RegisterOnSuccessBindData();
                jQuery.GetJSON(href, new Dictionary(), (Function)(object)new GenericOneArgDelegate(delegate(object data)
                {
                    cached[href] = data;
                    if (onSuccess != null)
                    {
                        onSuccess(data);
                    }
                    RaiseOnSuccessBindData();
                }));
            }
            else
            {
                if (onSuccess != null)
                {
                    onSuccess(dataJson);
                }
            }
        }
        
        static private string GetValueRadioSelector(DOMElement radioField, DOMElement element)
        {
            string selector = string.Format("input[popupId=\"{0}\"]", radioField.GetAttribute("popupId"));
            jQuery fields = ((jQuery)(object)element).QuerySelectorAll(selector);

            string result = "";
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                CheckBoxElement radioItem = (CheckBoxElement)fields[i];
                if (radioItem.Checked)
                {
                    result = radioItem.Value;
                    break;
                }
            }
            return result;
        }

        static private string GetValueRadio(DOMElement radioField, string parentId)
        {
            string selector = (parentId != "" ? "#" : "") + parentId;
            selector += string.Format(" input[popupId=\"{0}\"]", radioField.GetAttribute("popupId"));
            jQuery fields = JQueryFactory.JQuery(selector);

            string result = "";
            int count = fields.Length;
            for (int i = 0; i < count; i++)
            {
                CheckBoxElement radioItem = (CheckBoxElement)fields[i];
                if (radioItem.Checked)
                {
                    result = radioItem.Value;
                    break;
                }
            }
            return result;
        }

        int queueBindDataComplete = 0;
        public EmptyEventHandler OnSuccessBindData = null;
        private void RegisterOnSuccessBindData()
        {
            queueBindDataComplete++;
        }
        private void RaiseOnSuccessBindData()
        {
            queueBindDataComplete--;
            if (queueBindDataComplete == 0 && OnSuccessBindData != null)
            {
                OnSuccessBindData();
            }
        }
    }
}
